﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

namespace client.controls
{
    /// <summary>
    /// Simplized RichTextBox
    /// </summary>
    public partial class SimpleRTextBox : UserControl
    {
        private Image _selectedImage = null;
        private const int DefaultImageHeight = 100;
        public RichTextBox RichTextBox => _rtb;

        public SimpleRTextBox()
        {
            InitializeComponent();
            _rtb.DisablePasting();
        }

        /// <summary>
        /// insert image at caret position
        /// </summary>
        /// <param name="filePath">image file full path</param>
        public void InsertImage(string filePath)
        {
            if (File.Exists(filePath))
            {
                var bitmap = new BitmapImage();
                bitmap.BeginInit();
                bitmap.UriSource = new Uri(filePath);
                bitmap.CacheOption = BitmapCacheOption.OnLoad;
                bitmap.EndInit();
                InsertBitmapImageAtCaret(bitmap);
            }
        }

        /// <summary>
        /// Export content to bytes in XamlPackage format
        /// </summary>
        public byte[] ExportData()
        {
            byte[] data = null;
            TextRange range = new TextRange(_rtb.Document.ContentStart, _rtb.Document.ContentEnd);
            using (MemoryStream stream = new MemoryStream())
            {
                range.Save(stream, DataFormats.XamlPackage);
                data = stream.ToArray();
            }

            return data;
        }

        public void ImportData(byte[] data)
        {
            TextRange range = new TextRange(_rtb.Document.ContentStart, _rtb.Document.ContentEnd);
            using (MemoryStream stream = new MemoryStream(data))
            {
                range.Load(stream, DataFormats.XamlPackage);
            }
        }

        private void _rtb_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            //handle right lcick to block the context menu
            e.Handled = true;
        }

        /// <summary>
        /// show slider of zooming if right click on image
        /// </summary>
        private void _rtb_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _selectedImage = null;
            Point hitPoint = e.GetPosition(_rtb);
            HitTestResult result = VisualTreeHelper.HitTest(_rtb, hitPoint);

            if (result.VisualHit is Image img)
            {
                _slider.Value = img.Height / 10;
                _selectedImage = img;
                _sliderPopup.HorizontalOffset = 50;
                _sliderPopup.VerticalOffset = -50;
                _sliderPopup.IsOpen = true;
            }
            else
            {
                if (_sliderPopup.IsOpen)
                {
                    _sliderPopup.IsOpen = false;
                }
            }
        }

        /// <summary>
        /// handle key combination of paste
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _rtb_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            // paste image for the ctrl+v
            if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.V)
            {
                if (Clipboard.ContainsImage())
                {
                    InsertBitmapImageAtCaret(Clipboard.GetImage());
                }
                else if (Clipboard.ContainsText())
                {
                    _rtb.Selection.Text = Clipboard.GetText();
                }
                else if (Clipboard.ContainsFileDropList())
                {
                    var imgFilePaths = Clipboard.GetFileDropList().Cast<string>().Where(f =>
                    {
                        var extension = Path.GetExtension(f);
                        return extension == ".jpg" || extension == ".jpeg" || extension == ".png" || extension == ".bmp" ||
                               extension == ".gif" || extension == ".tiff" || extension == ".ico";
                    });

                    foreach (string filePath in imgFilePaths)
                    {
                        if (File.Exists(filePath))
                        {
                            BitmapImage bitmap = new BitmapImage();
                            bitmap.BeginInit();
                            bitmap.UriSource = new Uri(filePath);
                            bitmap.CacheOption = BitmapCacheOption.OnLoad;
                            bitmap.EndInit();
                            InsertBitmapImageAtCaret(bitmap);
                        }
                    }
                }

                e.Handled = true;
            }
        }

        /// <summary>
        /// close slider if lost focus
        /// </summary>
        private void _slider_LostFocus(object sender, RoutedEventArgs e)
        {
            _sliderPopup.IsOpen = false;
        }

        private void _slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (_selectedImage != null)
            {
                _selectedImage.Height = e.NewValue * 10;
            }
        }

        /// <summary>
        /// insert bitmap image at caret position
        /// </summary>
        private void InsertBitmapImageAtCaret(BitmapSource bitmap)
        {
            var image = new Image();
            image.Source = bitmap;
            image.Stretch = Stretch.Uniform;
            image.Height = DefaultImageHeight;
            new InlineUIContainer(image, _rtb.CaretPosition);

            _rtb.CaretPosition = _rtb.CaretPosition.Paragraph.ContentEnd;
            _rtb.Focus();
        }
    }

    public static class RichTextBoxExtensions
    {
        public static void DisablePasting(this RichTextBox richTextBox)
        {
            DataObject.AddPastingHandler(richTextBox, (sender, e) =>
            {
                e.CancelCommand();
            });
        }
    }
}
